home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************/
- /* */
- /* Program copylpt */
- /* */
- /* Usage: copylpt filename [PRINTER] */
- /* where filename is file to be copied (upper, lower or mixed case) */
- /* and optional argument PRINTER is the printer to copy to */
- /* (upper, lower or mixed case) */
- /* PRN, 1 or LPT1 for LPT1, */
- /* 2 or LPT2 for LPT2 or */
- /* 3 or LPT3 for LPT3. */
- /* If PRINTER is not specified, copy to LPT1 */
- /* Returns ERRORLEVEL 0 if file filename was copied to the printer */
- /* 1 if PRINTER is not available */
- /* 2 if PRINTER is available, but file filename is */
- /* not available. */
- /* 3 if both PRINTER and file filename are */
- /* available, but there was some error copying */
- /* filename to PRINTER. */
- /* 100 for certain system errors. */
- /* */
- /* I designed copylpt to copy a file to a printer if the printer */
- /* is available and then inform a batch file of its success or failure. */
- /* I wanted my AUTOEXEC.BAT file to copy an user-defined character set to */
- /* my Epson printer if possible without stopping for a critical error if */
- /* the printer is off. */
- /* If the filename's path does not start with a back slash and it does, */
- /* not specify a drive, copylpt looks first at the filename itself, then */
- /* appends it to any paths specified in a PATH-like environment variable */
- /* which has the same name as the filename's extension, then appends it to */
- /* any paths in the PATH enviroment variable. Under DOS 3 or later, it */
- /* finally appends it to the calling program's drive and path. */
- /* copylpt requires DOS 2.0 or later to run. */
- /* The ERRORLEVEL of 100 occurs only in the event of a compiler or */
- /* system failure. */
- /* */
- /* I compiled copylpt and its subfunctions for use with Lattice C, */
- /* Version 3. Some of their features which may not be portable are: */
- /* _DOS is a Lattice C system variable which contains the DOS major */
- /* version. */
- /* fileno() is an UNIX function which returns the file handle for a */
- /* file pointer. */
- /* Lattice classes onerror(action) as a MSDOS function. onerror(1) */
- /* preeempts the MSDOS critical error handler. onerror(0) restores the */
- /* MSDOS critical error handler. */
- /* getfc(fh, cw) returns 0 if fh is a valid file handle, -1 otherwise. */
- /* If it is a valid file handle, the function sets cw to the */
- /* word for the file. Bit 7 is 0 for a disk file. See DOS interrupt 44H, */
- /* AL = 0, for more information about the characteristic word */
- /* union REGS is a Lattice union which lets the registers become */
- /* arguments to functions which invoke 8086 interrupts. Two functions */
- /* use it. Both return an int containing the flags after the interrupt. */
- /* intdos invokes interrupt 21H with input registers as the first */
- /* argument and returns the value of the registers after the interrupt as */
- /* the second argument. int86 invokes the interrupt specified by the */
- /* first argument with input registers as the second argument. It returns */
- /* the value of the registers after the interrupt as the third argument. */
- /* fopene is a Lattice 3 variant version of fopen which automatically */
- /* searches the environment as described above. */
- /* stcgfn and stcgfp are Lattice expressions which get a file name */
- /* node (name and extension) and path respectively to string variables. */
- /* The path does not have a trailing "\" */
- /* Lattice function getdsk returns 0 if the default drive is A:, */
- /* 1 if it is B:, etc. */
- /* Lattice function getcd takes a drive number as its first argument, */
- /* with 0 for the default drive, 1 for A:, etc. It returns the current */
- /* directory in the variable pointed at by its second argument. The */
- /* current directory does not include either the drive letter or the */
- /* trailing back-slash. In particular, it returns an empty string for */
- /* the root directory. */
- /* dfind is a Lattice implementation of the DOS function which returns */
- /* the directory entry which matches the input file name. Sets the DOS */
- /* information in a structure which has a type FILEINFO, and it returns */
- /* 0 if it can make a match, -1 otherwise. */
- /* getenv(name) is a Lattice C function which returns a pointer to the */
- /* information following the = sign in the DOS environment string of the */
- /* form NAME=information. */
- /* strupr converts a string to upper case. */
- /* Lattice C sets a variable errno to a non-zero value if a standard */
- /* library function detects an error. It never automatically resets */
- /* errno. Errno is in error.h. */
- /* */
- /* Full identifiers in this program conform to the proposed ANSI */
- /* standard of at most 31 significant characters, and they are different */
- /* within the first 8 characters. Lattice C includes a -n compiler */
- /* switch which changes the number of significant characters in */
- /* identifiers from 8 to 39. While this program works without it, I */
- /* designed them to use it. */
- /* */
- /* This file requires the functions in files CHECKLPT.C and FOPEN1.C */
- /* to compile and run */
- /* */
- /* Lew Paper */
- /* 4/18/87 */
- /***************************************************************************/
-
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <dos.h>
- #include <error.h>
- #include <stdlib.h>
-
- extern char _DOS; /* Lattice system variable. DOS major */
- /* version number */
-
- static int printer_number = 1;
- static char printer_name[] = "LPT1";
- static FILE *printer_fp;
- static int handle;
-
- static char file_name[65];
- static FILE *file_fp;
-
- extern int errno; /* fgetc sets this to non-zero */
- static char error_message_end[90]; /* Pointer to end of error message */
-
- /* Prototypes for external functions */
- int handle_check_lpt_available(int);
- FILE *fopene_program(char *, char *, char *);
-
- #define CHECK_NAME(LEGAL) !strcmpi(argv[2], "LEGAL")
- #define CALLING_NAME argv[0]
- #define CARRY_FLAG 1
-
- static void close_device()
-
- {
- if (fclose(printer_fp))
- fprintf(stderr, "\nError in closing printer %s\n\n", printer_name);
- }
-
- static void close_file()
-
- {
- if (fclose(file_fp))
- fprintf(stderr, "\nError in closing file %s\n\n", file_name);
- }
-
- /* Write an error message to stderr, close LPT2 or LPT3 and exit with */
- /* ERRORLEVEL = 1 */
- static void no_copy_end()
-
- {
- fprintf(stderr, "Unable to copy file %s\nto printer %s because",
- file_name, printer_name);
- fputs(error_message_end, stderr);
- fputs("\n\n", stderr);
- if (printer_number > 1)
- close_device();
- }
-
- static void write_printer_error()
-
- {
- close_file(); /* Close input file */
- sprintf(error_message_end, " Error writing to printer %s",
- printer_name);
- no_copy_end();
- exit(3);
- }
-
- static void usage()
-
- {
- fputs("Usage: copylpt filename [PRINTER]\n", stderr);
- fputs(" where filename is file to be copied ",stderr);
- fputs("(upper, lower or mixed case)\n", stderr);
- fputs(" and optional argument PRINTER is the printer to copy to\n",
- stderr);
- fputs(" (upper, lower or mixed case)\n", stderr);
- fputs(" PRN, 1 or LPT1 for LPT1,\n", stderr);
- fputs(" 2 or LPT2 for LPT2 or\n", stderr);
- fputs(" 3 or LPT3 for LPT3.\n", stderr);
- fputs(" If PRINTER is not specified, copy to LPT1\n", stderr);
- fputs("Returns ERRORLEVEL 0 if file filename was copied to the printer\n",
- stderr);
- fputs(" 1 if file filename was not copied ", stderr);
- fputs("to the printer\n", stderr);
- fputs(" 100 for certain system errors.\n\n", stderr);
-
- exit(1);
- } /* usage */
-
- static void get_device_handle()
-
- {
- int cw; /* Characteristic word for file */
-
- /* PC DOS 3.1 opens printers which are off or not installed with */
- /* no error indication, so I can not test a critical error here. I */
- /* preempted the critical error handler because I am not sure that */
- /* some version of DOS might not treat opening a printer which */
- /* doesn't exist as a critical error. */
- if (onerror(1)) /* Preempt MSDOS critical error */
- /* handler. */
- {
- fputs("onerror(1) failed in get_device_handle\n\n", stderr);
- exit(100);
- }
-
- if (printer_number == 1)
- printer_fp = freopen("LPT1", "wb", stdprt);
- else
- printer_fp = fopen(printer_name, "wb");
- if (!printer_fp)
- {
- fprintf(stderr, "Unable to open device %s\n\n", printer_name);
- exit(1);
- }
-
- if (getfc((handle = fileno(printer_fp)), &cw) || !(cw & 0x0080))
- /* Invalid handle */
- {
- fprintf(stderr, "There is no device driver %s installed\n\n",
- printer_name);
- close_device();
- exit(1);
- }
-
- /* The Lattice C Manual doesn't say exactly how onerror() works. */
- /* I turned it off here to protect its being turned back on in */
- /* FILE_check_lpt_available */
- if (onerror(0)) /* Restore MSDOS critical error */
- {
- fputs("onerror(0) failed in get_device_handle\n\n", stderr);
- close_device();
- exit(100);
- }
-
- } /* get_device_handle */
-
- main(argc, argv)
- int argc;
- char *argv[];
-
- {
- int c;
-
- /* Check for DOS 2.0 or later */
- if (!_DOS)
- {
- fputs("COPYLPT requires DOS 2.0 or later.\n\n", stderr);
- exit(1);
- }
-
- switch (argc)
- {
- case 1: /* No file name specified */
- usage(); /* Display usage and exit with */
- /* ERRORLEVEL = 1. */
- break;
-
- case 2: /* Default printer */
- break;
-
- default: /* argc >= 3. Set up printer name */
- /* and handle. */
- if (CHECK_NAME(prn) || CHECK_NAME(1) || CHECK_NAME(lpt1))
- /* Defensive programming. LPT1 is */
- /* the original default printer, so */
- /* these assignments are not */
- /* necessary. */
- printer_number = 1;
- else if (CHECK_NAME(2) || CHECK_NAME(lpt2))
- printer_number = 2;
- else if (CHECK_NAME(3) || CHECK_NAME(lpt3))
- printer_number = 3;
- else
- usage(); /* Display usage and exit with */
- /* ERRORLEVEL = 1. */
- sprintf(printer_name, "LPT%d", printer_number);
- break;
- }
-
- get_device_handle();
-
- /* Transfer upper case of file name from argv[1] to file_name. */
- (void) strcpy(file_name, argv[1]);
- (void) strupr(file_name);
-
- /* Check if printer is available */
- if (handle_check_lpt_available(handle))
- {
- sprintf(error_message_end, " printer %s was not available",
- printer_name);
- no_copy_end();
- exit(1);
- }
-
- file_fp = fopene_program(file_name, "rb", CALLING_NAME);
- if (!file_fp)
- {
- sprintf(error_message_end, " file %s could not be opened",
- file_name);
- no_copy_end();
- exit(2);
- }
-
- errno = 0; /* Clear any prior errors */
- while ((c = getc(file_fp)) != EOF)
- if (putc(c, printer_fp) == EOF)
- write_printer_error();
- if (errno) /* Check for input error */
- write_printer_error();
-
- close_file();
- close_device();
- fprintf(stderr, "copylpt wrote file %s to printer %s\n\n",
- file_name, printer_name);
-
- } /* main */